﻿using Microsoft.KtmIntegration;
using RockBus.DataContracts;
using RockBus.ServiceModel;
using RockBus.Transport.Interfaces;
using System;
using System.IO;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using System.Xml;

namespace RockBus.Transport.File
{
    public class FileTransport : ITransport
    {
        private FileTransport()
        {
            this.MessageVersion = MessageVersion.Default;
            this.WriterSettings = new XmlWriterSettings();
            this.WriterSettings.CloseOutput = true;
            this.WriterSettings.Indent = true;
            this.WriterSettings.OmitXmlDeclaration = false;
            this.WriterSettings.ConformanceLevel = ConformanceLevel.Auto;
            this.WriterSettings.Encoding = Encoding.UTF8;
        }

        public FileTransport(EndpointInfo endpoint)
            : this()
        {
            this.Endpoint = endpoint;
        }

        public FileTransport(EndpointInfo endpoint, MessageVersion messageVersion)
            : this(endpoint)
        {
            this.MessageVersion = messageVersion;
        }

        public EndpointInfo Endpoint { get; set; }

        public MessageVersion MessageVersion { get; private set; }

        public XmlWriterSettings WriterSettings { get; private set; }

        public Task<Message> StartTransportMessage(Message message)
        {
            return Task<Message>.Factory.StartNew(() =>
            {
                this.WriteFile(message);
                return null;
            });
        }

        private void WriteFile(Message message)
        {
            string filename = Path.Combine(
                this.Endpoint.Address,
                string.Format("{0}.xml", Guid.NewGuid().ToString()));
            FileInfo fi = new FileInfo(filename);

            FileStream fs = null;
            if (this.Endpoint.TransactionScopeOption != TransactionScopeOption.Suppress)
            {
                fs = TransactedFile.Open(
                    fi.FullName,
                    FileMode.Create,
                    FileAccess.Write,
                    FileShare.Write);
            }
            else
            {
                fs = fi.Open(
                    FileMode.Create,
                    FileAccess.Write,
                    FileShare.Write);
            }

            using (var marshalledMessage = message.MarshalMessage(message.Headers.To, this.MessageVersion))
            using (var writer = XmlWriter.Create(fs, WriterSettings))
            {
                marshalledMessage.WriteMessage(writer);
            }
        }
    }
}